/*
 * TraceMain.c
 *
 *  Created on: 2012/06/07
 *      Author: guanxiaoying
 */

#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include "../tracedef.h"
#include "TraceAst.h"

static S4  traceMainLoop( VOID ){
	U2 usTemp;
	AST astMaxstack = 0;
	S4 rc = TRACEEXIT_SUCCESS;

	while( rc == TRACEEXIT_SUCCESS )
	{
		if(  stCurrTraceInfo.astTable < MIN_ARRAY )  /*  カレントトレース対象連番が0  */
		{
			astMaxstack = stTraceStackAccess.getMax();
			usTemp = stTraceStackAccess.times.get( astMaxstack );
			if( usTemp != TRACE_OBJECT_END ){
				rc = TraceStack( STACK_TEST );
				if( rc != TRACEEXIT_SUCCESS )
				{
					continue;
				}
			}else{
				rc = TraceStack( STACK_PULL );
				if( rc != TRACEEXIT_SUCCESS )
				{
					continue;
				}
				if( stCurrTraceInfo.usKind == TR_KIND_DECLARATION )  /*  カレントトレース対象がテーブルチェーン  */
				{
					stCurrTraceInfo.astTable = stCurrTraceInfo.astNext;
					if( stCurrTraceInfo.astTable > 0 )
					{
						stCurrTraceInfo.astNext = CDeclaration.getNextDeclaration( stCurrTraceInfo.astTable  );
					}
				}
				else if( stCurrTraceInfo.usKind == TR_KIND_DECLARATOR )  /*  カレントトレース対象が文  */
				{
					stCurrTraceInfo.astTable = stCurrTraceInfo.astNext;
					if( stCurrTraceInfo.astTable  > 0 )
					{
						stCurrTraceInfo.astNext = CDeclarator.getNextDeclarator( stCurrTraceInfo.astTable  );
					}
				}
				else if( stCurrTraceInfo.usKind == TR_KIND_STATEMENT )  /*  カレントトレース対象が文  */
				{
					stCurrTraceInfo.astTable = stCurrTraceInfo.astNext;
					if( stCurrTraceInfo.astTable  > 0 )
					{
						stCurrTraceInfo.astNext = CStatement.getNextStmt( stCurrTraceInfo.astTable  );
					}
				}
				else if( stCurrTraceInfo.usKind == TR_KIND_EXPRESSION )  /*  カレントトレース対象が文  */
				{
					stCurrTraceInfo.astTable = stCurrTraceInfo.astNext;
					if( stCurrTraceInfo.astTable  > 0 )
					{
						stCurrTraceInfo.astNext = 0;
					}
				}
				else if( stCurrTraceInfo.usKind == TR_KIND_INITIALIZER )  /*  カレントトレース対象が文  */
				{
					stCurrTraceInfo.astTable = stCurrTraceInfo.astNext;
					if( stCurrTraceInfo.astTable  > 0 )
					{
						stCurrTraceInfo.astNext = CInitializer.getNextOne( stCurrTraceInfo.astTable );
					}
				}
				else
				{
					stCurrTraceInfo.astTable = 0;
					stCurrTraceInfo.astNext = 0;
				}
			}
		}
		if(  stCurrTraceInfo.astTable < MIN_ARRAY )    /*  カレントトレース対象連番が0  */
		{
			continue;
		}
		if( stCurrTraceInfo.usKind == TR_KIND_DECLARATION )  /* カレントトレース対象がテーブルチェーン */
		{
			if( ( ulOpt & OPT_DECLARATION ) != 0  )  /*  テーブルチェーン情報をトレースする場合   */
			{
				rc = TraceDeclaration( );
			}
			else
			{
				stCurrTraceInfo.astTable = 0;   /* カレントトレース対象を空とする */
				stCurrTraceInfo.astNext = 0;    /* カレントトレース対象のnextを空とする  */
			}

		}
		else if( stCurrTraceInfo.usKind == TR_KIND_DECLARATOR ) /* カレントトレース対象が初期化式 */
		{
			if ( (ulOpt & OPT_DECLARATOR) != 0 )
			{
				rc = TraceDeclarator();
				if( rc == TRACEEXIT_FATAL )
				{
					return rc;
				}
			}
			else
			{
				stCurrTraceInfo.astTable = 0;   /* カレントトレース対象を空とする */
				stCurrTraceInfo.astNext = 0;    /* カレントトレース対象のnextを空とする  */
			}
		}
		else if( stCurrTraceInfo.usKind == TR_KIND_STATEMENT )   /*  カレントトレース対象が文  */
		{

			if( ( ulOpt & OPT_STATEMENT ) != 0 )          /* 文情報をトレースする場合	 */
			{
				rc = TraceStmt( );
				if( rc == TRACEEXIT_FATAL )
				{
					return rc;
				}
			}

			else
			{
				stCurrTraceInfo.astTable = 0;   /* カレントトレース対象を空とする */
				stCurrTraceInfo.astNext = 0;    /* カレントトレース対象のnextを空とする  */
			}

		}
		else if( stCurrTraceInfo.usKind == TR_KIND_EXPRESSION )        /* カレントトレース対象が式  */
		{
			if( ( ulOpt & OPT_EXPRESSION) != 0 )      /*  式をトレースする場合  */
			{
				rc = TraceExpEntry( );
				if( rc == TRACEEXIT_FATAL )
				{
					return rc;
				}
			}

			else
			{
				stCurrTraceInfo.astTable = 0;   /* カレントトレース対象を空とする */
				stCurrTraceInfo.astNext = 0;    /* カレントトレース対象のnextを空とする  */
			}
		}
		else if( stCurrTraceInfo.usKind == TR_KIND_INITIALIZER ) /* カレントトレース対象が初期化式 */
		{
			if ( (ulOpt & OPT_INITEXPRLIST) != 0 )
			{
				rc = TraceInitExpList();
				if( rc == TRACEEXIT_FATAL )
				{
					return rc;
				}
			}
			else
			{
				stCurrTraceInfo.astTable = 0;   /* カレントトレース対象を空とする */
				stCurrTraceInfo.astNext = 0;    /* カレントトレース対象のnextを空とする  */
			}
		}
		else
		{
			stCurrTraceInfo.astTable = 0;   /* カレントトレース対象を空とする */
			stCurrTraceInfo.astNext = 0;    /* カレントトレース対象のnextを空とする  */
		}

	}
	if( rc == TRACEEXIT_END )
	{
		rc = TRACEEXIT_SUCCESS;
	}
	return ( rc );
}
/******************************************************************
* 関 数 名 : TraceTranslationUnit
* 機    能 : トレース開始
* 引    数 :U2 usKind, AST astObj
* 戻 り 値 :	TRACEEXIT_SUCCESS
* 		 	TRACEEXIT_END
* 			TRACEEXIT_FATAL
* 詳細内容 :
*******************************************************************/

S4	DLL_EXPORT TraceTranslationUnit( AST astObj, U4 ulOpt1, U4 ulEvent1,
		S4 (*pfunc1)(U2, AST, U4 ), CALLBACK_FUNCALL pGetFuncInfo  )
{
	lEventSec = ulEvent1;
	lEvent = 0;
	lEvent |= EVENT_MODULE_MASK & ulEvent1;
	ulOpt = ulOpt1;
	pfunc = pfunc1;

   /*  カレントトレース対象をusKind,astObjとする */
	stCurrTraceInfo.usKind = TR_KIND_DECLARATION;
	stCurrTraceInfo.astTable = CTranslationUnit.getDeclaration(astObj);

	return traceMainLoop();
}


/******************************************************************
* 関 数 名	 : S4	TraceStack(U2 usDo )
* 機    能	 :
* 引    数	 : 	usDo	STACK_PUSH		テーブルTRACE_STACKINFOに1行を追加して、stCurrTraceInfoの情報を　その行に入れる
			STACK_TEST		テーブルTRACE_STACKINFOに最後の行の情報を　stCurrTraceInfoに入れる
			STACK_PULL		テーブルTRACE_STACKINFOに最後の行の情報を　stCurrTraceInfoに入れて、テーブルTRACE_STACKINFOを1行削除する

* 戻 り 値	 : 	TRACEEXIT_SUCCESS
* 			TRACEEXIT_FATAL
* 			TRACEEXIT_END
* 詳細内容 :
*******************************************************************/
S4	TraceStack(U2 usDo )
{
	S4	rc = TRACEEXIT_SUCCESS;
	S4 lTemp;
	S4 iRet = 0;
	AST astMaxTraceStack;
	/*if  usDo == STACK_PUSH		*/
	if( usDo == STACK_PUSH )
	{
		stTraceStackAccess.alloc(1);
		astMaxTraceStack = stTraceStackAccess.getMax();

		/*1 次のtrace対象を退避  */
		stTraceStackAccess.nextObject.set( astMaxTraceStack , stCurrTraceInfo.astNext );
		/*3 trace対象を退避  */
		stTraceStackAccess.currObject.set( astMaxTraceStack , stCurrTraceInfo.astTable );
		/*4 現在の関数を退避  */
		stTraceStackAccess.traceFunction.set( astMaxTraceStack , stCurrTraceInfo.astTraceSub );
		/*5 trace対象の種類を退避  */
		stTraceStackAccess.kind.set( astMaxTraceStack , stCurrTraceInfo.usKind );
		/*6 trace回数を初期化  */
		stTraceStackAccess.times.set( astMaxTraceStack , 0 );
		if(lEventSec & EVENT_TRPUSH)
		{
			iRet = pfunc( stCurrTraceInfo.usKind, stCurrTraceInfo.astTable , lEvent | EVENT_TRPUSH );
			if( iRet > TRACEEXIT_WARNING )
			{
				return iRet;
			}
		}
	}
	else if( usDo == STACK_TEST )
	{
		/*	テーブルTRACE_STACKINFOの行の総数を　「スタック数」に代入する。（Trace_GetMaxByKind）	*/
		astMaxTraceStack = stTraceStackAccess.getMax();
		if (astMaxTraceStack >= MIN_ARRAY )
		{
			lTemp = stTraceStackAccess.kind.get( astMaxTraceStack );
			/* 1 */
			stCurrTraceInfo.astNext = stTraceStackAccess.nextObject.get( astMaxTraceStack );
			/* 2 */
			stCurrTraceInfo.astTable = stTraceStackAccess.currObject.get( astMaxTraceStack );
			/* 4 */
			stCurrTraceInfo.astTraceSub = stTraceStackAccess.traceFunction.get( astMaxTraceStack );
			/* 5 */
			stCurrTraceInfo.usKind = lTemp;
			/* 6 */
		}
		else
		{
			stCurrTraceInfo.astTable = 0;
			stCurrTraceInfo.astTraceSub = 0;
			stCurrTraceInfo.usKind = 0;
			stCurrTraceInfo.astNext = 0;
			rc = TRACEEXIT_END;
		}
	}
	else
	{

		astMaxTraceStack = stTraceStackAccess.getMax();
		if (astMaxTraceStack >= MIN_ARRAY )
		{
			lTemp = stTraceStackAccess.kind.get( astMaxTraceStack );
			/* 1 */
			stCurrTraceInfo.astNext = stTraceStackAccess.nextObject.get( astMaxTraceStack );
			/* 2 */
			stCurrTraceInfo.astTable = stTraceStackAccess.currObject.get( astMaxTraceStack );
			/* 4 */
			stCurrTraceInfo.astTraceSub = stTraceStackAccess.traceFunction.get( astMaxTraceStack );
			/* 5 */
			stCurrTraceInfo.usKind = lTemp;
			if(lEventSec & EVENT_TRPULL)
			{
				iRet = pfunc( stCurrTraceInfo.usKind, stCurrTraceInfo.astTable , lEvent | EVENT_TRPULL);
				if( iRet > TRACEEXIT_WARNING )
				{
					return iRet;
				}
			}
			stTraceStackAccess.alloc(-1);
		}
		else
		{
			stCurrTraceInfo.astTable = 0;
			stCurrTraceInfo.astTraceSub = 0;
			stCurrTraceInfo.usKind = 0;
			stCurrTraceInfo.astNext = 0;
			if(lEventSec & EVENT_TRPULL)
			{
				iRet = pfunc( stCurrTraceInfo.usKind, stCurrTraceInfo.astTable , lEvent | EVENT_TRPULL);
				if( iRet > TRACEEXIT_WARNING )
				{
					return iRet;
				}
			}
			rc = TRACEEXIT_END;/* TRACEEXIT_END  */
		}
	}

	return( rc );
}
/******************************************************************
* 関 数 名 : 	TraceClose
* 機    能 : 	メモリを解放する
* 引    数 : 	無し
* 戻 り 値 :	TEACEEXIT_SUCCESS	正常終了
* 		 	TEACEEXIT_FATAL	        致命エラー
* 詳細内容 : 1	トレース用テーブル情報のメモリ解放
*					※MemTmpClose
*				メモリ解放失敗した場合、EXIT_FATALをリターンする
*			2	EXIT_SUCCESSをリターンする
*******************************************************************/
S4	DLL_EXPORT TraceClose( VOID )
{
	stTraceStackAccess.clear();
	stTraceFuncAccess.clear();
	return(TRACEEXIT_SUCCESS);
}
/* end of file */


